#include <Windows.h>
#include <atltime.h>
#include "uti_barseries_broad.h"
using namespace std;
#pragma warning(disable : 4996)

extern char gTradingDay[15];

BarSeries_broad::BarSeries_broad(BarInfo* pbarinfo, unsigned int sersize, void (*p)(), BarData* pstart, unsigned int* pindex)
{
	memcpy(&m_serinfo.barinfo, pbarinfo, sizeof(BarInfo));
	m_serinfo.sersize = sersize;
	m_serinfo.p = p;
	notfirstbar = false;

	m_pcur = pstart;
	m_pindex = pindex;
	m_dbindex = *m_pindex;




	char year[5] = {0};		
	char month[3] = {0};	
	char day[3] = {0};		

	char* pglobal = gTradingDay;
	memcpy(year, pglobal, 4);	pglobal += 4;
	memcpy(month, pglobal, 2);	pglobal += 2;
	memcpy(day, pglobal, 2);	pglobal += 2;
	m_year = atoi(year);		m_month = atoi(month);		m_day = atoi(day);
	

	char* inst = m_serinfo.barinfo.instru;

	if ('I' == inst[0] && 'F' == inst[1])
		bCommidity = false;
	else
		bCommidity = true;
}

BarSeries_broad::~BarSeries_broad()
{

}



LONGLONG BarSeries_broad::GetStartspan(SYSTEMTIME& ticksys)
{

	CTime tickctime(ticksys);
	CTime startctime(m_pcur->starttime);
	CTimeSpan startspan = tickctime - startctime;

	//get timespan related to bartype
	LONGLONG istartspan = 0;
	if (m_serinfo.barinfo.type == Bartype::sec)
		istartspan = startspan.GetTotalSeconds();
	else if (m_serinfo.barinfo.type == Bartype::min)
	{
		LONGLONG minspan = startspan.GetTotalMinutes();

		if (ticksys.wSecond < m_pcur->starttime.wSecond)
			istartspan = minspan + 1;
		else
			istartspan = minspan;

	}		
	else if (m_serinfo.barinfo.type == Bartype::day)
		istartspan = startspan.GetDays();

	return istartspan;
}

bool BarSeries_broad::Addtick(MarketData* tick)
{
	SYSTEMTIME ticksys;
	//SetSystime(&ticksys, tick->TradingDay, tick->UpdateTime, tick->UpdateMillisec);
	SetSystime(&ticksys, tick->UpdateTime, tick->UpdateMillisec);


	if (0 ==RUN_STATE || 1 ==RUN_STATE)
	{
	} 
	else
	{
		if (false == SatisfyTime(ticksys))
		{
			printf("[Addtick] SatisfyTime Failed\n");
			return false;
		}
	}
	
	if (notfirstbar == false)
	{		
		UpdateBar(tick, true, &ticksys);
		notfirstbar = true;
	}	
	else if ((m_serinfo.barinfo.type == Bartype::tick && m_pcur->tickcnt == m_serinfo.barinfo.cnt) ||
		(m_serinfo.barinfo.type != Bartype::tick && GetStartspan(ticksys) >= m_serinfo.barinfo.cnt ))
	{
		//m_pmemman->NextUnitPointer(&m_pcur,&m_index);//get cur bar pointer and index
		SetBarend();
		(*m_pindex)++;
		m_pcur++;
		UpdateBar(tick, true, &ticksys);
	}
	else
	{
		UpdateBar(tick, false, &ticksys);
	}

	return true;
}



void BarSeries_broad::UpdateBar(MarketData* tick, bool updatestarttm, SYSTEMTIME* pticksys)
{
	if (true == updatestarttm)
	{
		memcpy(&m_pcur->starttime, pticksys, sizeof(m_pcur->starttime));//used for write file record and bar complete judgement
		m_pcur->open = tick->LastPrice;;
		m_pcur->high = tick->LastPrice;
		m_pcur->low = tick->LastPrice;
		m_pcur->UpperLimitPrice = tick->UpperLimitPrice;
		m_pcur->LowerLimitPrice = tick->LowerLimitPrice;
		m_pcur->index = *m_pindex;
	}	
	memcpy(&m_pcur->curtime, pticksys, sizeof(m_pcur->curtime));//used for write file record and bar complete judgement
	m_pcur->tickcnt++;

	m_pcur->LastPrice = tick->LastPrice;
	m_pcur->close = tick->LastPrice;
	if (m_pcur->high < tick->LastPrice) m_pcur->high = tick->LastPrice;
	if (m_pcur->low > tick->LastPrice) m_pcur->low = tick->LastPrice;
	m_pcur->AveragePrice = tick->AveragePrice;
	m_pcur->vol += tick->Volume;
	m_pcur->Turnover += tick->Turnover;
	m_pcur->OpenInterest = tick->OpenInterest;
	m_pcur->OpenInterestDiff = tick->OpenInterest - tick->PreOpenInterest;

	strcpy(m_pcur->inst, tick->InstrumentID);

	if (tick->OpenPrice > tick->UpperLimitPrice || tick->OpenPrice < tick->LowerLimitPrice)
		m_pcur->exch_open = 0;
	else
		m_pcur->exch_open = tick->OpenPrice;

	if (tick->ClosePrice > tick->UpperLimitPrice || tick->ClosePrice < tick->LowerLimitPrice)
		m_pcur->exch_close = 0;
	else
		m_pcur->exch_close = tick->ClosePrice;

	if (tick->HighestPrice > tick->UpperLimitPrice || tick->HighestPrice < tick->LowerLimitPrice)
		m_pcur->exch_high = 0;
	else
		m_pcur->exch_high = tick->HighestPrice;

	if (tick->LowestPrice > tick->UpperLimitPrice || tick->LowestPrice < tick->LowerLimitPrice)
		m_pcur->exch_low = 0;
	else
		m_pcur->exch_low = tick->LowestPrice;


	if (tick->BidPrice1 > tick->UpperLimitPrice || tick->BidPrice1 < tick->LowerLimitPrice)
	{
		m_pcur->BidPrice1 = 0;
		m_pcur->BidVolume1 = 0;
	}
	else
	{
		m_pcur->BidPrice1 = tick->BidPrice1;
		m_pcur->BidVolume1 = tick->BidVolume1;
	}

	if (tick->AskPrice1 > tick->UpperLimitPrice || tick->AskPrice1 < tick->LowerLimitPrice)
	{
		m_pcur->AskPrice1 = 0;
		m_pcur->AskVolume1 = 0;
	}
	else
	{
		m_pcur->AskPrice1 = tick->AskPrice1;
		m_pcur->AskVolume1 = tick->AskVolume1;
	}

}



void BarSeries_broad::SetSystime(SYSTEMTIME* ptm, const char* pdate, const char* ptime, int millisec)
{
	
	//set date
	unsigned int date = atoi(pdate);

	ptm->wDay = date % 100;

	date = date / 100;

	ptm->wMonth = date % 100;

	date = date / 100;

	ptm->wYear = date;



	ptm->wHour = atoi(ptime);

	ptime += 3;

	ptm->wMinute = atoi(ptime);

	ptime += 3;

	ptm->wSecond = atoi(ptime);

	ptm->wMilliseconds = millisec;


}

void BarSeries_broad::SetSystime(SYSTEMTIME* ptm, const char* ptime, int millisec)
{
	//set date

	ptm->wDay = m_day;

	ptm->wMonth = m_month;

	ptm->wYear = m_year;


	//set time
	ptm->wHour = atoi(ptime);

	ptime += 3;

	ptm->wMinute = atoi(ptime);

	ptime += 3;

	ptm->wSecond = atoi(ptime);

	ptm->wMilliseconds = millisec;

}

// 0 ---out of 8:59~15:30
// 1 ---out of 8:59~9:00
// 2 ---out of 9:00~15:30
bool BarSeries_broad::SatisfyTime(SYSTEMTIME& tm)
{
	/*if (8 == tm.wHour && 59 == tm.wHour)
	{
	}
*/

	if (true == bCommidity)
	{
		if ( (tm.wHour >= 9) &&
			(tm.wHour <= 14 || (tm.wHour == 15 && tm.wMinute == 0 && tm.wSecond == 0))
			)
		{
			return true;
		}
	}
	else
	{
		if ( 
			((tm.wHour == 9 && tm.wMinute >= 15) || tm.wHour > 9) &&
			(tm.wHour <= 14 || (tm.wHour == 15 && tm.wMinute <= 15))
			)
		{
			return true;
		}
	}

	
	return false;
}